import React, { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { IViewer } from './interface';
import { ScreenshotsContext } from './Screenshot';
import ScreenshotsViewerBar from './ScreenshotsViewerBar';
interface IPoint {
    x: number;
    y: number;
}
interface IProps {
    onChange: any;
}
export default (props: IProps) => {
    const context = useContext(ScreenshotsContext);
    const { state, dispatch } = context;
    const { onChange } = props;

    const viewerRef = useRef<HTMLDivElement>(null);
    const canvasRef = useRef<HTMLCanvasElement>(null);

    // move和resize的标志
    const [actionType, setActionType] = useState(null);
    // 鼠标起始位置
    const [point, setPoint] = useState<IPoint | null>(null);
    // 保存初始的viewer数据
    const [viewer, setViewer] = useState<IViewer | null>(null);

    const size = useMemo(() => {
        const { viewer } = state;
        if (viewer) {
            const { x1, y1, x2, y2 } = viewer;
            return {
                x: x1,
                y: y1,
                width: x2 - x1,
                height: y2 - y1,
            };
        } else {
            return {
                x: 0,
                y: 0,
                width: 0,
                height: 0,
            };
        }
    }, [state]);

    const cursor = useMemo(() => {
        return 'grab';
    }, []);

    const pointers = useMemo(() => {
        const pointers = ['top', 'top-right', 'right', 'right-bottom', 'bottom', 'bottom-left', 'left', 'left-top'];
        return state.action ? [] : pointers;
    }, [state]);

    const move = useCallback(
        (e: MouseEvent) => {
            if (!state.viewer || !point) return;
            const x = e.clientX - point.x;
            const y = e.clientY - point.y;
            const { x1, y1, x2, y2 } = state.viewer;
            onChange({
                x1: x1 + x,
                y1: y1 + y,
                x2: x2 + x,
                y2: y2 + y,
            });
        },
        [onChange, state, point],
    );

    const resize = useCallback((event: MouseEvent) => {}, []);

    const onMouseMove = useCallback(
        (event: MouseEvent) => {
            const { viewer, action } = state;
            if (!viewer) return;
            if (!action) {
                if (actionType === 'move') {
                    move(event);
                } else if (actionType) {
                    resize(event);
                }
            } else {
            }
        },
        [state, move, resize, actionType],
    );

    const onMouseUp = useCallback(
        (e: MouseEvent) => {
            const { viewer, action } = state;
            if (!viewer) return;
            if (!action) {
                if (actionType === 'move') {
                    dispatch({
                        type: 'clearCursor',
                    });
                }
                dispatch({
                    type: 'setViewer',
                    data: {
                        ...state.viewer,
                        resizing: false,
                        moving: false,
                    },
                });
            } else {
            }
        },
        [dispatch, state, actionType],
    );

    const onMouseDown = (e: React.MouseEvent<HTMLDivElement, MouseEvent>, type: any) => {
        const { viewer, action } = state
        if (!viewer) return
        if (!action) {
            if (!type || e.button !== 0) return
            setActionType(type)
            setPoint({ x: e.clientX, y: e.clientY })
            setViewer(state.viewer)
            if (actionType === 'move') {
                dispatch({
                    type: 'setState',
                    data: {
                        viewer: { ...state.viewer, moving: true },
                        cursor: 'grabbing'
                    }
                })
            } else {
                dispatch({
                    type: 'resizing',
                })
            }
        } else {

        }

    };

    useLayoutEffect(() => {
        window.addEventListener('mousemove', onMouseMove);
        window.addEventListener('mouseup', onMouseUp);
        return () => {
            window.removeEventListener('mousemove', onMouseMove);
            window.removeEventListener('mouseup', onMouseUp);
        };
    }, [onMouseMove, onMouseUp]);

    const draw = useCallback(() => {
        const { image, width, height, stack } = state;
        const ctx = canvasRef.current?.getContext('2d');
        if (!image?.el || !ctx) return;
        const { x, y, width: w, height: h } = size;
        const rx = image.width / width;
        const ry = image.height / height;
        ctx.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0);
        ctx.clearRect(0, 0, w, h);
        ctx.drawImage(image.el, x * rx, y * ry, w * rx, h * ry);
        stack.forEach((item) => item.draw(ctx, item.history[0], item)); // action draw
    }, [state, size]);
    
    useEffect(() => {
        draw();
    }, [draw]);

    return (
        <div className="screenshots-viewer" style={{ display: state.viewer ? 'block' : 'none' }}>
            <div
                ref={viewerRef}
                className="screenshots-viewer-body"
                style={{
                    left: size.x,
                    top: size.y,
                    width: size.width,
                    height: size.height,
                }}
            >
                <canvas ref={canvasRef} width={size.width * devicePixelRatio} height={size.height * devicePixelRatio} />
                <div
                    className="screenshots-viewer-border"
                    style={{ cursor: state.cursor }}
                    onMouseDown={(e) => onMouseDown(e, 'move')}
                />
                {pointers.map((pointer) => (
                    <div key={pointer} className={`screenshots-viewer-pointer-${pointer}`}></div>
                ))}
            </div>
            <ScreenshotsViewerBar />
        </div>
    );
};
